/*
 * 描          述:  <描述>
 * 修  改   人:  Administrator
 * 修改时间:  2014年6月19日
 * <修改描述:>
 */
package com.tx.component.dailytask.executor.impl;

import java.time.LocalDate;
import java.util.List;

import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;

import com.tx.component.dailytask.executor.AbstractDailyTaskExecutor;
import com.tx.component.dailytask.task.impl.IterableDailyTask;
import com.tx.core.exceptions.util.AssertUtils;

/**
 * 批量任务执行器<br/>
 *     这里这个实现是有问题的，需要进行调整<br/>
 * @author  Administrator
 * @version  [版本号, 2014年6月19日]
 * @see  [相关类/方法]
 * @since  [产品/模块版本]
 */
public class IterableDailyTaskExecutor<T>
        extends AbstractDailyTaskExecutor<IterableDailyTask<T>>
        implements InitializingBean {
    
    /** 事务模板类 */
    private TransactionTemplate localTransTemplate;
    
    /** <默认构造函数> */
    public IterableDailyTaskExecutor() {
        super();
    }
    
    /** <默认构造函数> */
    public IterableDailyTaskExecutor(String taskBeanName,
            IterableDailyTask<T> task,
            PlatformTransactionManager transactionManager) {
        super(taskBeanName, task, transactionManager);
    }
    
    /**
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        AssertUtils.notEmpty(this.beanName, "beanName is empty.");
        AssertUtils.notNull(task, "task is null.");
        AssertUtils.notNull(transactionManager, "transactionManager is null.");
        
        this.localTransTemplate = new TransactionTemplate(
                this.transactionManager, new DefaultTransactionDefinition(
                        TransactionDefinition.PROPAGATION_REQUIRES_NEW));
    }
    
    /**
     * @param executeDate
     * @return
     */
    @Override
    public LocalDate doExecute(final LocalDate date) {
        //获取任务总数，用以核对最后执行任务数量
        int total = this.task.count(date);
        IterableDailyTask<T> finalTask = this.task;
        
        //计数器
        int count = 0;
        int executeCount = 0;
        do {
            executeCount = this.localTransTemplate
                    .execute(new TransactionCallback<Integer>() {
                        //考虑到mysql的事务隔离性，nextAdapter,以及hasNextAdapter应该放入事务中进行取值
                        @Override
                        public Integer doInTransaction(
                                TransactionStatus status) {
                            //执行任务,并对计数器进行累加
                            List<T> datas = finalTask.next(date);
                            if (CollectionUtils.isEmpty(datas)) {
                                return 0;
                            }
                            for (T data : datas) {
                                finalTask.execute(data, date);
                            }
                            return datas.size();
                        }
                    });
            //统计总共执行了多少条
            count = count + executeCount;
        } while (executeCount > 0);
        this.logger.info("taskId:{}.任务执行错误.计数器:{};总任务数:{}",
                new Object[] { this.task.getId(), String.valueOf(count),
                        String.valueOf(total) });
        LocalDate nextExecuteLocalDate = this.task.end(date);
        return nextExecuteLocalDate;
    }
}
